/******************************************************************************
* Copyright (C) 2010-2011 Computer Graphics Systems Group at the 
* Hasso-Plattner-Institute (HPI), Potsdam, Germany.
*
* Lecture : Geovisualisation Summer Term 2011
* Exercise: Processing Rendering OpenStreetMap Data 
*
* Author: sebastian.pasewaldt@hpi.uni-potsdam.de
*
******************************************************************************/

#ifndef __QTVIEWER_H__
#define __QTVIEWER_H__


//[-------------------------------------------------------]
//[ Includes                                              ]
//[-------------------------------------------------------]
#include "ConfigWidget.h"

#include <QtCore/QTimer>
#include <QtGui/QWidget>

#include <osgViewer/CompositeViewer>

#include <osg/Vec3>
#include <osg/Node>
#include <osg/MatrixTransform>

class OSMHandler;
class CoordTransformer;

//[-------------------------------------------------------]
//[ Classes                                               ]
//[-------------------------------------------------------]
/**
*  @brief
*    OSG viewer for Qt
*/
class QtViewer : public QWidget, public osgViewer::CompositeViewer
{
    Q_OBJECT

    //[-------------------------------------------------------]
    //[ Public functions                                      ]
    //[-------------------------------------------------------]
    public:
		/**
		*  @brief
		*    Constructor
		*/
        QtViewer();

		osgViewer::View* getView(){return m_view;};
	
		/**
		*  @brief
		*    computes the distance of a start and an end vector
		*/
		double computeDistance(osg::Vec3 start, osg::Vec3 end);

    public slots:
        void onIntersectionInfo(QString);
        void onSetMarker(osg::Vec3*);

	
	//[-------------------------------------------------------]
	//[ Private functions                                      ]
	//[-------------------------------------------------------]

	private:
		
		/**
		*  @brief
		*    parses the OSM file
		*/
		void parseOSMFile();
		
		/**
		*  @brief
		*    builds a flat terrain based on the bounding box of all scene elements
		*    should be called after the OSM file is parsed and geometry has been generated
		*/
		void buildTerrain();
		
		/**
		*  @brief
		*    normalizes coordinates to world coordinates
		*/
		void normalizeCoords(double& x, double& y);
		
		/**
		*  @brief
		*    init scene things
		*/
		void initScene();
		
		/**
		*  @brief
		*    sets the camera to a suitable position
		*/
		void initCameraPosition();

        void buildSceneGraph();
        void collectVertices(osg::Vec3Array* vertices, int wayIdx);
        void collectVerticesForRelations(osg::Vec3Array* vertices, int wayRef);

        void transformToRange01();
        double euclideanDistanceInMeters(double lat1, double long1, double lat2, double long2);

	//[-------------------------------------------------------]
	//[ Private data                                          ]
	//[-------------------------------------------------------]
		double m_x,m_y;

		osg::ref_ptr<osg::MatrixTransform> m_rootNode;
		
		osg::ref_ptr<osg::Group> m_2DGroup;
		osg::ref_ptr<osg::Group> m_terrainGroup;
		osg::ref_ptr<osg::Group> m_streetGroup;
		osg::ref_ptr<osg::Group> m_naturalGroup;
		
		osg::ref_ptr<osg::Group> m_3DGroup;
		osg::ref_ptr<osg::Group> m_buildingGroup;
		osg::ref_ptr<osg::Group> m_PoIGroup;

		osg::ref_ptr<osg::Group> m_markerGroup;

		osgViewer::View *m_view;
		ConfigWidget* m_configWidget;

        OSMHandler* m_osmHandler;
        CoordTransformer* m_transformer;

    //[-------------------------------------------------------]
    //[ Protected functions                                   ]
    //[-------------------------------------------------------]
    protected:
		/**
		*  @brief
		*    Create rendering widget
		*
		*  @param x
		*    X coordinate
		*  @param y
		*    Y coordinate
		*  @param w
		*    Width
		*  @param h
		*    Height
		*  @param scene
		*    Root scene node
		*
		*  @return
		*    Rendering widget
		*/
        QWidget *createViewWidget(int x, int y, int w, int h, osg::Node *scene);

		/**
		*  @brief
		*    Called on paint event
		*
		*  @param event
		*    Paint event
		*/
        virtual void paintEvent(QPaintEvent *event);


    //[-------------------------------------------------------]
    //[ Protected data                                        ]
    //[-------------------------------------------------------]
    protected:
        QTimer m_timer;     /**< Timer used for updating the frame */

};


#endif // __QTVIEWER_H__
